import { CellView, Graph, Node } from '@antv/x6'
import { Dnd } from '@antv/x6-plugin-dnd'
import { register } from '@antv/x6-vue-shape'
import { setNodePort } from './otherFun'
import { renderAddNode } from './mainProcessData'
import OrdinaryNode from '@renderer/page/canvas/components/OrdinaryNode.vue'
import ProductNode from '@renderer/page/canvas/components/ProductNode.vue'
import AddNode from '@renderer/page/canvas/components/AddNode.vue'
import TransportNode from '@renderer/page/canvas/components/TransportNode.vue'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Selection } from '@antv/x6-plugin-selection'
import { useCanvasParameterStore } from './canvasParameter'
import { storeToRefs } from 'pinia'
import { useLayerStore } from '../resourceBar/layer'
import { Snapline } from '@antv/x6-plugin-snapline'
import Crossing from '@renderer/page/canvas/components/Crossing.vue'
import { snaplineNodeShape } from './canvasConst'
import { Transform } from '@antv/x6-plugin-transform'

export let bgCanvas = {} as Graph
export let canvas = {} as Graph

//dnd
export let dnd = {} as Dnd

const computedPorts = (position: string, mark: 'input' | 'output' | 'twoway', offset: any) => {
  return {
    position: {
      name: position,
      args: offset
    },
    markup: [
      {
        tagName: 'rect',
        selector: 'portBody'
      }
    ],
    attrs: {
      portBody: {
        width: 10,
        height: 10,
        radius: 0,
        strokeWidth: 1,
        stroke:
          mark === 'input'
            ? '#5F95FF'
            : mark === 'output'
              ? '#3ac575'
              : {
                  type: 'linearGradient',
                  attrs: {
                    x1: '0%', // 起点x坐标
                    y1: '0%', // 起点y坐标
                    x2: '100%', // 终点x坐标
                    y2: '100%' // 终点y坐标
                  },
                  stops: [
                    { offset: '0%', color: '#5F95FF' },
                    { offset: '100%', color: '#3ac575' }
                  ]
                },
        fill:
          mark === 'input'
            ? '#eff4ff'
            : mark === 'output'
              ? '#edfaef'
              : {
                  type: 'linearGradient',
                  attrs: {
                    x1: '0%', // 起点x坐标
                    y1: '0%', // 起点y坐标
                    x2: '100%', // 终点x坐标
                    y2: '100%' // 终点y坐标
                  },
                  stops: [
                    { offset: '0%', color: '#eff4ff' },
                    { offset: '100%', color: '#edfaef' }
                  ]
                },
        magnet: true,
        style: {
          visibility: 'visible'
        }
      }
    }
  }
}

//自定义连接桩
export const customPorts = {
  topIn: computedPorts('top', 'input', { dx: -5, dy: 3 }),
  topOut: computedPorts('top', 'output', { dx: -5, dy: 3 }),
  topTwoway: computedPorts('top', 'twoway', { dx: -5, dy: 3 }),
  bottomIn: computedPorts('bottom', 'input', { dx: -5, dy: -13 }),
  bottomOut: computedPorts('bottom', 'output', { dx: -5, dy: -13 }),
  bottomTwoway: computedPorts('bottom', 'twoway', { dx: -5, dy: -13 }),
  leftIn: computedPorts('left', 'input', { dx: 3, dy: -5 }),
  leftOut: computedPorts('left', 'output', { dx: 3, dy: -5 }),
  leftTwoway: computedPorts('left', 'twoway', { dx: 3, dy: -5 }),
  rightIn: computedPorts('right', 'input', { dx: -13, dy: -5 }),
  rightOut: computedPorts('right', 'output', { dx: -13, dy: -5 }),
  rightTwoway: computedPorts('right', 'twoway', { dx: -13, dy: -5 })
}

//初始化画布实例
export const initCanvas = (): void => {
  //设置背景画布
  bgCanvas = new Graph({
    container: document.getElementById('bgCanvas') as HTMLElement,
    autoResize: true,
    grid: {
      type: 'doubleMesh',
      size: 10,
      visible: true,
      args: [
        {
          color: '#e0e0e080',
          thickness: 1
        },
        {
          color: '#e0e0e0',
          thickness: 1,
          factor: 10
        }
      ]
    },
    background: {
      color: '#f7f7f7'
    }
  })

  //设置画布
  canvas = new Graph({
    container: document.getElementById('operateCanvas') as HTMLElement,
    autoResize: true,
    //平移
    panning: {
      enabled: false,
      eventTypes: ['leftMouseDown']
    },
    //缩放
    mousewheel: {
      enabled: true,
      factor: 1.1
    },
    //网格
    grid: {
      size: 1,
      visible: true
    },

    connecting: {
      //是否可以连接到空白处
      allowBlank(args: any) {
        const shape = args.edge.shape
        if (shape === 'ordinary-edge') {
          return false
        }
        return true
      },

      //是否可以自己连自己
      allowLoop(args: any) {
        if (args.edge.shape === 'road-edge') {
          return true
        }

        if (args.sourceCell.id !== args.targetCell.id) {
          return true
        } else {
          return false
        }
      },

      //是否允许连接到节点（非连接桩）
      allowNode() {
        return false
      },

      allowEdge() {
        return true
      },

      //是否允许创建相同连线
      allowMulti: 'withPort',

      // 吸附半径
      snap: {
        radius: 15
      },

      //创建连接线
      createEdge({ sourceCell }) {
        if (sourceCell.shape === 'cross-node') {
          return this.addEdge({
            shape: 'road-edge'
          })
        } else {
          return this.addEdge({
            shape: 'ordinary-edge'
          })
        }
      },

      //点击连接桩时，先判断是否需要新增连接边
      validateMagnet({ cell, magnet }) {
        if (this.isNode(cell)) {
          const node = cell as Node
          const ports = node.getPorts()
          //获取magnet中port属性
          const portId = magnet.getAttribute('port')
          const targetPort = ports.find((port) => port.id === portId)
          const prohibitPorts = ['topIn', 'bottomIn', 'leftIn', 'rightIn']
          if (prohibitPorts.includes(targetPort?.group || '')) {
            return false
          }
        }
        return true
      },
      //验证是否可以连接
      validateConnection({ edge, targetMagnet }) {
        if (edge?.shape === 'road-edge') {
          return true
        }

        const prohibitPorts = ['topOut', 'bottomOut', 'leftOut', 'rightOut']
        const targetPort = targetMagnet?.getAttribute('port-group')
        if (prohibitPorts.includes(targetPort || '')) {
          return false
        }
        return !!targetMagnet
      }
    },

    interacting: (cellView: CellView) => {
      const { isCanvasNodeInteractive, isEdgeMovable } = storeToRefs(useCanvasParameterStore())
      if (!isCanvasNodeInteractive.value) {
        return false
      }

      const { lockNodeIds } = storeToRefs(useLayerStore())
      if (lockNodeIds.value.includes(cellView.cell.id)) {
        return false
      }

      return {
        edgeMovable: isEdgeMovable.value
      }
    }
  })

  //使用插件
  //键盘快捷键
  canvas.use(
    new Keyboard({
      enabled: true
    })
  )
  //框选
  canvas.use(
    new Selection({
      rubberband: true,
      eventTypes: ['leftMouseDown'],
      showNodeSelectionBox: true
    })
  )
  //对齐线
  canvas.use(
    new Snapline({
      enabled: false,
      sharp: true,
      tolerance: 5,
      filter: (node: Node) => {
        if (snaplineNodeShape.includes(node.shape)) {
          return true
        } else {
          return false
        }
      }
    })
  )
  //图形变换
  canvas.use(
    new Transform({
      resizing: {
        enabled: () => {
          const { isGraphTransform } = useCanvasParameterStore()
          return isGraphTransform
        },
        minWidth: 10,
        minHeight: 0,
        orthogonal: false,
        restrict: false,
        preserveAspectRatio: false
      }
    })
  )

  dnd = new Dnd({
    target: canvas,
    //拖拽结束时的回调函数
    validateNode(droppingNode: Node): boolean {
      //给节点设置连接桩
      setNodePort(droppingNode)

      //渲染进程给主进程发送消息，添加节点
      renderAddNode(droppingNode)

      //返回false，这里不添加节点
      return false
    }
  })
}

//注册节点与连接线
export const registerNodeAndEdge = (): void => {
  //注册普通节点，长100，宽100
  register({
    shape: 'ordinary-node',
    width: 100,
    height: 100,
    component: OrdinaryNode,
    ports: {
      groups: customPorts
    }
  })

  //创建产品节点
  register({
    shape: 'product-node',
    width: 20,
    height: 20,
    component: ProductNode
  })

  //注册十字路节点
  register({
    shape: 'cross-node',
    width: 120,
    height: 120,
    component: Crossing,
    ports: {
      groups: customPorts
    }
  })

  //创建搬运流节点
  register({
    shape: 'transport-node',
    width: 100,
    height: 100,
    component: TransportNode
  })

  //注册添加事件的节点
  register({
    shape: 'add-node',
    width: 18,
    height: 18,
    component: AddNode,
    attrs: {
      body: {
        magnet: true
      }
    }
  })

  //自定义顶点区域
  Graph.registerNode(
    'custom-port-node',
    {
      inherit: 'polygon',
      width: 100,
      height: 100,
      attrs: {
        body: {
          fill: '#d6ddff66',
          stroke: 'transparent',
          points: '0,0 100,0 100,100 0,100',
          event: 'customPortNodeClick'
        }
      }
    },
    true
  )

  //注册编辑多边形的顶点小圆圈
  Graph.registerNode(
    'free-edit-circle',
    {
      inherit: 'circle',
      width: 4,
      height: 4,
      attrs: {
        body: {
          fill: '#fff',
          stroke: '#0087dc',
          strokeWidth: 1
        }
      }
    },
    true
  )
  //注册编辑多边形的边
  Graph.registerEdge(
    'free-edit-edge',
    {
      inherit: 'edge',
      markup: [
        {
          tagName: 'path',
          selector: 'p1'
        },
        {
          tagName: 'path',
          groupSelector: 'arrow',
          selector: 'a1'
        }
      ],
      attrs: {
        p1: {
          stroke: '#0087dc',
          strokeWidth: 0.7,
          connection: true,
          fill: 'none'
        },
        a1: {
          d: 'M -2 0 0 -2 2 0 0 2 z',
          fill: '#fff',
          stroke: '#ED8A19',
          atConnectionRatio: 0.5,
          cursor: 'pointer',
          event: 'freeEditEdgeClick'
        }
      }
    },
    true
  )

  //注册纯文本节点
  Graph.registerNode(
    'text-node',
    {
      inherit: 'rect',
      width: 100,
      height: 25,
      markup: [
        {
          tagName: 'rect',
          selector: 'body'
        },

        {
          tagName: 'text',
          selector: 'label'
        }
      ],
      attrs: {
        rect: {
          fill: 'transparent',
          stroke: 'transparent'
        },
        label: {
          text: '自定义文字',
          fill: '#4E5969',
          fontSize: 15,
          fontWeight: 'regular',
          letterSpacing: 0,
          event: 'textNodeClick'
        }
      }
    },
    true
  )

  //注册普通连接线
  Graph.registerEdge(
    'ordinary-edge',
    {
      inherit: 'edge',
      anchor: 'center',
      connectionPoint: 'anchor',
      markup: [
        {
          tagName: 'path',
          selector: 'p1'
        },
        {
          tagName: 'path',
          groupSelector: 'arrow',
          selector: 'a1'
        }
      ],
      attrs: {
        p1: {
          connection: true,
          fill: 'none',
          stroke: '#A2B1C3',
          strokeWidth: 2,
          strokeLinejoin: 'round'
        },
        a1: {
          d: 'M 0 -6 8 0 0 6 z',
          fill: '#ED8A19',
          stroke: '#ED8A19',
          atConnectionRatio: 0.5,
          cursor: 'pointer'
        }
      }
    },
    true
  )

  //注册传送带鼠标拖下来的样式节点
  Graph.registerNode(
    'edge-drag-node',
    {
      inherit: 'rect',
      width: 150,
      height: 20,
      markup: [
        {
          tagName: 'rect',
          selector: 'body'
        },

        {
          tagName: 'text',
          selector: 'label'
        }
      ],
      attrs: {
        rect: {
          fill: 'transparent',
          stroke: '#c0c0c0',
          strokeWidth: 1
        },
        label: {
          text: '',
          fill: '#4E5969',
          fontSize: 13,
          textAnchor: 'middle'
        }
      }
    },
    true
  )

  //注册传送带
  Graph.registerEdge(
    'conveyor-belt',
    {
      inherit: 'edge',
      router: {
        name: 'orth'
      },
      connector: { name: 'rounded' },
      anchor: 'center',
      connectionPoint: 'anchor',
      markup: [
        {
          tagName: 'rect',
          selector: 'port'
        },
        {
          tagName: 'path',
          selector: 'p1'
        },
        {
          tagName: 'path',
          selector: 'p2'
        },
        {
          tagName: 'path',
          selector: 'p3'
        },
        {
          tagName: 'text',
          selector: 'describe'
        }
      ],
      attrs: {
        port: {
          y: -7,
          connection: true,
          width: 5,
          height: 15,
          fill: '#c0c0c0',
          atConnectionRatio: 0,
          magnet: true
        },
        p1: {
          connection: true,
          fill: 'none',
          stroke: '#c0c0c0',
          strokeWidth: 20,
          strokeLinejoin: 'round',
          event: 'conveyorClick'
        },
        p2: {
          connection: true,
          fill: 'none',
          stroke: '#f5f8ff',
          strokeWidth: 17,
          strokeLinejoin: 'round',
          event: 'conveyorClick'
        },
        p3: {
          connection: true,
          fill: 'none',
          stroke: '#c0c0c0',
          strokeWidth: 20,
          pointerEvents: 'none',
          strokeLinejoin: 'round',
          strokeDasharray: '1,15',
          event: 'conveyorClick'
        },
        describe: {
          atConnectionRatio: 0.5,
          textAnchor: 'middle',
          textVerticalAnchor: 'middle',
          fontSize: 13,
          fill: '#0087dc',
          text: '➤'
        }
      }
    },
    true
  )

  //注册道路连线
  Graph.registerEdge(
    'road-edge',
    {
      inherit: 'edge',
      router: {
        name: 'orth'
      },
      connector: { name: 'rounded' },
      anchor: 'center',
      connectionPoint: 'anchor',
      markup: [
        {
          tagName: 'path',
          selector: 'p1'
        },
        {
          tagName: 'path',
          selector: 'p2'
        }
      ],
      attrs: {
        p1: {
          connection: true,
          fill: 'none',
          stroke: '#A2B1C3',
          strokeWidth: 20,
          strokeLinejoin: 'round',
          event: 'roadEdgeClick'
        },
        p2: {
          connection: true,
          fill: 'none',
          stroke: '#d9c956',
          strokeWidth: 3,
          pointerEvents: 'none',
          strokeLinejoin: 'round',
          strokeDasharray: 5,
          event: 'roadEdgeClick'
        }
      }
    },
    true
  )

  //注册警戒线
  Graph.registerEdge(
    'warning-line',
    {
      inherit: 'edge',
      router: {
        name: 'orth'
      },
      connector: { name: 'rounded' },
      anchor: 'center',
      connectionPoint: 'anchor',
      markup: [
        {
          tagName: 'path',
          selector: 'p1'
        },
        {
          tagName: 'path',
          selector: 'p2'
        },
        {
          tagName: 'path',
          selector: 'p3'
        }
      ],
      attrs: {
        p1: {
          connection: true,
          fill: 'none',
          stroke: '#f5cf36ff',
          strokeWidth: 12,
          strokeLinejoin: 'round'
        },
        p2: {
          connection: true,
          fill: 'none',
          stroke: '#ffd83b',
          strokeWidth: 8,
          strokeDasharray: '10,10',
          strokeDashoffset: 0,
          strokeLinejoin: 'round'
        },
        p3: {
          connection: true,
          fill: 'none',
          stroke: '#3f4347',
          strokeWidth: 8,
          strokeDasharray: '10,10',
          strokeDashoffset: 10,
          strokeLinejoin: 'round'
        }
      }
    },
    true
  )
}

//初始化标尺
export const initRuler = (): void => {}
